#pragma once

#include "minicoro/minicoro.h"
#include "rtc_base/thread.h"
#include <functional>
#include <memory>

namespace p2pms
{

// CoroRunner 用于在指定的 rtc::Thread 上下文中安全地启动和管理 minicoro 协程。
class CoroRunner
{
public:
	// 定义一个合理的默认协程栈大小。
    static constexpr size_t kDefaultCoroStackSize = 256 * 1024; // 256 KB

	explicit CoroRunner(rtc::Thread* thread) : m_thread(thread) {}

	// func 是协程的主体逻辑。
	void Run(std::function<void()> func)
	{
		// 1. 为协程上下文分配内存。所有权将移交协程自身。
        auto* ctx = new CoroCtx();
        ctx->func = std::move(func);

        // 2. 初始化 minicoro 描述
        mco_desc desc = mco_desc_init(CoroEntry, kDefaultCoroStackSize);
        desc.user_data = ctx;

        // 3. 创建协程
        mco_create(&ctx->co, &desc);

        // 4. 在目标线程上启动协程。
        //    PostTask 的 lambda 不再持有任何智能指针，仅传递裸指针。
        m_thread->PostTask([co = ctx->co]() {
            // 首次 resume 协程。
            // 协程的生命周期将由 CoroEntry 函数在协程执行完毕后自行管理。
            mco_resume(co);
        });
	}

private:
	// 协程上下文，保存协程句柄和要执行的函数
	struct CoroCtx {
		mco_coro* co = nullptr;
		std::function<void()> func;
	};

	// minicoro 的入口函数
	static void CoroEntry(mco_coro* co)
	{
		auto* ctx = static_cast<CoroCtx*>(mco_get_user_data(co));
        
        // 5. 执行用户代码，并捕获任何可能的异常。
        try {
            if (ctx && ctx->func) {
                ctx->func();
            }
        } catch (const std::exception& e) {
            LOG_ERR("Exception caught in coroutine: {}", e.what());
        } catch (...) {
            LOG_ERR("Unknown exception caught in coroutine.");
        }

        // 6. 协程执行完毕，自我销毁。
        //    这是最关键的修复：确保协程和其上下文被正确清理。
        mco_destroy(co);
        delete ctx;
	}

	rtc::Thread* m_thread;
};

} // namespace p2pms